// cspell:disable

/******************************************************************************

[1] 数据模型 

- MeteorData
- MeteorResult

[2] 请求模型

- MeteorRequest
 
[3] 服务接口 

- IMeteorService 
 
******************************************************************************/

namespace mrs;

using System.Threading.Tasks;
using CSharpKit;
using CSharpKit.ComponentModel;
using meteoToolkit;
using meteoToolkit.Data;
using meteoToolkit.Radar;
using meteoToolkit.Radar.Metrad;
using Microsoft.Maui.Graphics;

/// <summary>
/// 
/// </summary>
public interface IMeteorService
{
    Task<MeteorSettings> Test();
    /// <summary>
    /// 取得天气雷达产品
    /// </summary>
    /// <param name="dataCode"></param>
    /// <param name="drawParam"></param>
    /// <returns></returns>
    Task<MeteorResult> GetMetradProductAsync(string dataCode, string drawParam);
}

public partial class MeteorService : IMeteorService
{
    public MeteorService(ILogger<MeteorService> logger, IConfigService configService)
    {
        _logger = logger;

        // 气象设置
        _meteorSettings = configService.GetConfig().MeteorSettings;

        // 基数据目录
        _baseDataDirectory = _meteorSettings.BaseDataDirectory;

        if (!Directory.Exists(_baseDataDirectory))
        {
            _logger.LogError("--- Error meteorSettings.BaseDataDirectory not exists");
        }

        // 输出目录
        _outputDirectory = _meteorSettings.OutputDirectory;

        // if (!Directory.Exists(_outputDirectory))
        // {
        //     // Directory.CreateDirectory(_outputDirectory!);
        //     _logger.LogInformation("--- Created output directory: {Directory}", _outputDirectory);
        // }

        _logger.LogInformation("--- _baseDataDirectory: {Directory}", _baseDataDirectory);
        _logger.LogInformation("--- _outputDirectory: {Directory}", _outputDirectory);
    }

    private readonly ILogger<MeteorService> _logger;
    private readonly MeteorSettings _meteorSettings;

    private readonly string _baseDataDirectory = "";
    private readonly string _outputDirectory = "";


    public async Task<MeteorSettings> Test()
    {
        await Task.Delay(50); // 模拟异步操作
        return _meteorSettings;
    }

    // 取得天气雷达产品
    public async Task<MeteorResult> GetMetradProductAsync(string dataCode, string drawParam)
    {
        try
        {
            // 基数据文件名 (test)
            var baseDataFile = Path.Combine(_baseDataDirectory, "a.bin");

            // 数据代码和绘制选项
            var eDataCode = Enum.Parse<MetradDataCode>(dataCode, true);
            var option = new PlotOption(drawParam);

            // 判断雷达产品 json 文件是否存在, 
            var notExists = !File.Exists(getJsonImageModelFileName(eDataCode));

            // 数据生成
            var mbr = (Enum.IsDefined(eDataCode) && eDataCode != MetradDataCode.NONE /*&& notExists*/)
                ? await metrad_build_cmp_async(baseDataFile, eDataCode, option) : null;
            // : await load_json_image_data_async(getJsonImageModelFileName(eDataCode));

            return new MeteorResult
            {
                DataCode = dataCode,
                DrawParam = drawParam,
                Success = true,
                OutputPath = _outputDirectory,
                ProcessedAt = DateTime.UtcNow,
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "--- Failed to get meteor data for DataCode: {DataCode}", dataCode);

            return new MeteorResult
            {
                DataCode = dataCode,
                DrawParam = drawParam,
                Success = false,
                ErrorMessage = ex.Message,
                ProcessedAt = DateTime.UtcNow
            };
        }
    }

    // {{END}}
}

// private
partial class MeteorService
{
    /// <summary>
    /// 构造组合产品 (CREF, VIL,  ETOP, ...）
    /// </summary>
    /// <param name="baseDataFile"></param>
    /// <param name="eDataCode"></param>
    /// <param name="option"></param>
    /// <returns> JsonImageModel String </returns>
    private async Task<MetradBuildResult?> metrad_build_cmp_async(string baseDataFile, MetradDataCode eDataCode, PlotOption option)
    {
        // MetradBuildResult
        var mbr = await Task.Run(() => metrad_build_cmp(baseDataFile, eDataCode, option));

        try
        {
            // 保存 JSON
            string pathFile = getJsonImageModelFileName(eDataCode);
            await saveJsonToFileAsync(pathFile, mbr.ImageJsonString);
            _logger.LogInformation("--- Successfully processed and saved JSON data: {pathFile}", pathFile);

            // 保存 IMAGE
            string imageFile = getImageFileName(eDataCode);
            await mbr.Image.SaveAsync(imageFile);
            _logger.LogInformation("--- Successfully processed and saved IMAGE data: {imageFile}", imageFile);
        }
        catch (System.Exception ex)
        {
            _logger.LogError(ex, "--- Error in metrad_build_cmp_async. ");
        }

        return mbr;

    }

    private async Task saveJsonToFileAsync(string pathFile, string jsonData)
    {
        try
        {
            // 使用异步文件写入
            await File.WriteAllTextAsync(pathFile, jsonData);
            // _logger.LogInformation("--- Successfully saved JSON data to file: {OutputPath}", pathFile);

        }
        catch (Exception ex)
        {
            // _logger.LogError(ex, "--- Error saving JSON data to file: {OutputPath}", pathFile);
            throw;
        }
    }

    private async Task<string> load_json_image_data_async(string pathFile)
    {
        try
        {
            _logger.LogInformation("JSON data load from: {Pathfile}", pathFile);

            // 使用异步文件读取
            return await File.ReadAllTextAsync(pathFile);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error load JSON data from file: {Pathfile}", pathFile);
            throw;
        }
    }

    /// <summary>
    /// 构造组合产品 (CREF, VIL,  ETOP, ...）
    /// </summary>
    /// <param name="baseDataFile"></param>
    /// <param name="eDataCode"></param>
    /// <param name="option"></param>
    /// <returns> JsonImageModel String </returns>
    /// <exception cref="InvalidOperationException"></exception>
    private MetradBuildResult? metrad_build_cmp(string baseDataFile, MetradDataCode eDataCode, PlotOption option)
    {
        _logger.LogInformation("--- metrad_build_cmp: DataCode = {eDataCode}, Draw = {Draw} ", eDataCode, option.Draw);

        try
        {
            var provider = new MetradFileProvider(baseDataFile, null);
            _logger.LogInformation("--- [metrad_build_cmp]> provider IsOpen = {IsOpen}", provider.IsOpen);


            var rfile = provider?.DataInstance as MetradFile;
            _logger.LogInformation("--- [metrad_build_cmp]> rfile.RefData Count = {Count}", rfile.RefData[0].Count);

            var dataInfo = rfile?.DataInfo as MetradFileDataInfo;
            // _logger.LogInformation("--- [metrad_build_cmp]> rfile.RefData Count = {Count}", rfile.RefData[0].Count);

            var processor = rfile?.Processor as MetradFileProcessor;
            // _logger.LogInformation("--- [metrad_build_cmp]> rfile.RefData Count = {Count}", rfile.RefData[0].Count);

            var sucess = processor?.Building(MetradBuildingParameter.CreateInstance(eDataCode, option));
            _logger.LogInformation("--- [metrad_build_cmp]> Building sucess? {sucess}", sucess);

            
            var y = rfile.ProductImage[(int)eDataCode];
            _logger.LogInformation("--- Building ok? {ok}", y);

            if (rfile.ProductImage[(int)eDataCode] is BitmapContext bitmapContext)
            {
                // 保存图像
                // string imagePath = Path.Combine(_outputDirectory, $"{eDataCode}.png");
                // bitmapContext.Save(imagePath);
                // _logger.LogInformation("--- Product image saved to: {ImagePath}", imagePath);

                // 转换为 base64 字符串
                // var imageBase64 = await bitmapContext.ToBase64StringAsnyc();

                // 生成包围四边形
                var polar = dataInfo?.Polar;
                var p1 = new Point(0, 0);
                var p2 = new Point(MetradConsts.ImageWidth - 1, MetradConsts.ImageHeight - 1);

                // 转换成经纬度坐标
                polar.XY2LonLat((int)p1.X, (int)p1.Y, out double lon0, out double lat0); // 左上角
                polar.XY2LonLat((int)p2.X, (int)p2.Y, out double lon1, out double lat1); // 右下角

                var jim = new JsonImageModel
                {
                    Name = eDataCode.Monicker(),

                    Rows = (int)(p2.Y - p1.Y + 1),
                    Cols = (int)(p2.X - p1.X + 1),

                    Lon1 = (float)lon0,
                    Lon2 = (float)lon1,

                    Lat1 = (float)lat1,
                    Lat2 = (float)lat0,

                    DateTime = dataInfo.DateTime, // 2020-12-01T01:00:00
                    ImageBase64 = bitmapContext.ToBase64String(),
                };

                var jimString = JsonSerializer.Serialize(jim);

                return new MetradBuildResult() { Image = bitmapContext, ImageJsonString = jimString };

            }

        }
        catch (Exception ex)
        {
            throw new InvalidOperationException($"--- MTK processing failed for file: {baseDataFile}", ex);
        }

        return null;
    }

    // 取得 image json 文件名
    private string getImageFileName(MetradDataCode eDataCode)
    {
        string pathFile = Path.Combine(_outputDirectory, $"{eDataCode}.png");
        return pathFile;
    }

    private string getJsonImageModelFileName(MetradDataCode eDataCode)
    {
        string pathFile = Path.Combine(_outputDirectory, $"{eDataCode}.json");
        return pathFile;
    }

    // {{END}}
}